//
//  HotFixViewController.m
//  TestPrj
//
//  Created by 陈晓星 on 2019/7/10.
//  Copyright © 2019 Xing. All rights reserved.
//

#import "HotFixViewController.h"
#import <Masonry.h>
#import "FixManager.h"
#import <Aspects/Aspects.h>
#import "UIButton+FixMultiClick.h"
#import "MSTestObject.h"
#import "MSTestObject+C1.h"
#import "MSTestObject+C2.h"

@interface HotFixViewController ()

@property(nonatomic,strong)UIButton *runBtn;
@property(nonatomic,strong)UIButton *hookBtn;
@property(nonatomic,strong)UIButton *fixBtn;
@property(nonatomic,strong)UILabel *label;

@end

@implementation HotFixViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    _label = [[UILabel alloc] init];
    _label.font = [UIFont systemFontOfSize:15];
    _label.textAlignment = NSTextAlignmentCenter;
    _label.textColor = [UIColor blackColor];
    _label.layer.borderColor = [UIColor lightGrayColor].CGColor;
    _label.layer.borderWidth = 0.5;
    [self.view addSubview:_label];
    
    _runBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [_runBtn setTitle:@"运行" forState:UIControlStateNormal];
    [_runBtn addTarget:self action:@selector(runBtnAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_runBtn];
    
    _hookBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [_hookBtn setTitle:@"aspects hook" forState:UIControlStateNormal];
    [_hookBtn addTarget:self action:@selector(hookAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_hookBtn];
    
    _fixBtn = [UIButton  buttonWithType:UIButtonTypeRoundedRect];
    [_fixBtn setTitle:@"热修复" forState:UIControlStateNormal];
    [_fixBtn addTarget:self action:@selector(fixBtnAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_fixBtn];
    
    [_label mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view.mas_top).offset(100);
        make.left.equalTo(self.view.mas_left).offset(10);
        make.right.equalTo(self.view.mas_right).offset(-10);
        make.height.equalTo(@40);
    }];
    
    [_runBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.view.mas_left).offset(10);
        make.right.equalTo(self.view.mas_right).offset(-10);
        make.top.equalTo(self.label.mas_bottom).offset(10);
        make.height.equalTo(@40);
    }];
    
    [_hookBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.view.mas_left);
        make.top.equalTo(self.runBtn.mas_bottom).offset(10);
        make.right.equalTo(self.view.mas_right);
        make.height.equalTo(@40);
    }];
    
    NSLog(@" == 1");
    [_fixBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        NSLog(@" == 2");
        make.left.equalTo(self.view.mas_left).offset(10);
        make.right.equalTo(self.view.mas_right).offset(-10);
        make.top.equalTo(self.hookBtn.mas_bottom).offset(10);
        make.height.equalTo(@40);
    }];
    NSLog(@" == 3");
    
    UIView *line = [UIView new];
    line.backgroundColor = [UIColor lightTextColor];
    [self.view addSubview:line];
    [line mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(10);
            make.right.mas_equalTo(-10);
            make.top.equalTo(self.fixBtn.mas_bottom).offset(10);
        make.height.mas_equalTo(1);
    }];
    UILabel *label1 = [UILabel new];
    label1.textColor = [UIColor lightGrayColor];
    label1.font = [UIFont systemFontOfSize:12];
    label1.numberOfLines = 0;
    label1.text = @"1、使用method swizzling的时候要注意有没有继承关系，UIButton+FixMultiClick如果在是扩展UIControl的话是能正常用的，但如果改成在UIButton中扩展的话，在UIControl空间站点击的时候就会报错：[UIControl cs_acceptEventTime]: unrecognized selector；\n2、在多个Category中使用method swizzling同一个方法:1、两个Category中，若swizzling自定义方法名相同，则自定义的方法不会调用。因为两次交换IMP正好不变；2、两个Category中，如swizzling自定义方法名不同，则自定义的方法都会被调用，调用顺序Compile Sources中在后边的先调用。";
    [self.view addSubview:label1];
    [label1 mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(10);
        make.right.mas_equalTo(-10);
            make.top.equalTo(line.mas_bottom).offset(10);
    }];
    
    UIButton *mButton1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [mButton1 setTitle:@"Button(0.01)" forState:UIControlStateNormal];
    [mButton1 addTarget:self action:@selector(intervalAction1) forControlEvents:UIControlEventTouchUpInside];
    mButton1.cs_acceptEventInterval = 0.01;
    [self.view addSubview:mButton1];
    UIButton *mButton2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [mButton2 setTitle:@"Button(2.0)" forState:UIControlStateNormal];
    [mButton2 addTarget:self action:@selector(intervalAction2) forControlEvents:UIControlEventTouchUpInside];
    mButton2.cs_acceptEventInterval = 2.0;
    [self.view addSubview:mButton2];
    UIControl *mControl = [UIControl new];
    [mControl addTarget:self action:@selector(intervalAction3) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:mControl];
    UILabel *mCLabel = [UILabel new];
    mCLabel.text = @"UIControl";
    mCLabel.textColor = [UIColor blueColor];
    [mControl addSubview:mCLabel];
    [mButton1 mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(10);
            make.top.equalTo(label1.mas_bottom).offset(10);
            make.height.mas_equalTo(44);
    }];
    [mButton2 mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(mButton1.mas_right).offset(10);
            make.top.equalTo(label1.mas_bottom).offset(10);
            make.height.mas_equalTo(44);
        make.width.equalTo(mButton1.mas_width);
    }];
    [mControl mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(mButton2.mas_right).offset(10);
            make.top.equalTo(label1.mas_bottom).offset(10);
            make.height.mas_equalTo(44);
        make.width.equalTo(mButton1.mas_width);
        make.right.mas_equalTo(-10);
    }];
    [mCLabel mas_makeConstraints:^(MASConstraintMaker *make) {
            make.edges.mas_equalTo(UIEdgeInsetsZero);
    }];
}

- (void)fixBtnAction:(UIButton *)sender {
    
    _fixBtn.enabled = NO;
    _hookBtn.enabled = NO;
    
    [FixManager fixIt];
    
    NSString *js = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"hotFix" ofType:@"js"] encoding:NSUTF8StringEncoding error:nil];
    
    [FixManager evalString:js];
    
//    NSString *fixScriptString = @" \
//    fixInstanceMethodReplace('MightyCrash', 'divideUsingDenominator:', function(instance, originInvocation, originArguments){ \
//    if (originArguments[0] == 0) { \
//    console.log('zero goes here'); \
//    } else { \
//    runInvocation(originInvocation); \
//    } \
//    }); \
//    \
//    ";
}

- (void)runBtnAction:(UIButton *)sender {
    
    _label.text = @"there is a bug.";
    
    [self func1];
    [self func2];
    [self func3];
}

- (void)hookAction {
    
    _fixBtn.enabled = NO;
    _hookBtn.enabled = NO;
    
    [HotFixViewController aspect_hookSelector:@selector(func1) withOptions:AspectPositionBefore usingBlock:^{
        NSLog(@"hook before");
    } error:nil];
    
    [HotFixViewController aspect_hookSelector:@selector(func2) withOptions:AspectPositionAfter usingBlock:^{
        NSLog(@"hook after");
    } error:nil];
    
    [HotFixViewController aspect_hookSelector:@selector(func3) withOptions:AspectPositionInstead usingBlock:^{
        NSLog(@"hook instead");
    } error:nil];
}

- (void)func1 {
    NSLog(@"===========");
    NSLog(@"%s",__func__);
}

- (void)func2 {
    NSLog(@"===========");
    NSLog(@"%s",__func__);
}

- (void)func3 {
    NSLog(@"===========");
    NSLog(@"%s",__func__);
}

- (void)intervalAction1 {
    NSLog(@"%s",__func__);
}
- (void)intervalAction2 {
    NSLog(@"%s",__func__);
}
- (void)intervalAction3 {
    NSLog(@"%s",__func__);
    NSLog(@"============");
    
    MSTestObject *obj = [MSTestObject new];
    [obj originMethod0];
    NSLog(@"------------");
    [obj originMethod1];
    NSLog(@"------------");
    [obj originMethod2];
}

@end
